<template>
	<view class="next-tree">
		<view class="next-tree-mask" :class="{ show: showTree }" @tap="_cancel"></view>
		<!-- :style="'top:'+top"  放在组件中不要top设置为0-->
		<view class="next-tree-cnt" :class="{ show: showTree, 'next-tree-cnt-page': uiMode === 'page' }">
			<view v-if="_showTreeBar" class="next-tree-bar">
				<view class="next-tree-bar-cancel" :style="{ color: cancelColor }" hover-class="hover-c" @tap="_cancel"> 取消 </view>
				<view class="next-tree-bar-title" :style="{ color: titleColor }">
					{{ customTitle }}
				</view>
				<view class="next-tree-bar-btns">
					<view
						v-if="['checkbox', 'radio'].indexOf(funcMode) !== -1"
						class="next-tree-bar-cancel"
						:style="{ color: cancelColor }"
						hover-class="hover-c"
						@tap="_clear"
					>
						清空
					</view>
					<view v-else-if="funcMode === 'edit'" class="next-tree-bar-cancel" :style="{ color: cancelColor }" hover-class="hover-c" @tap="_revert">
						还原
					</view>
					<view class="btn-divid"></view>
					<view class="next-tree-bar-confirm" :style="{ color: _themeColor }" hover-class="hover-c" @tap="_confirm"> 确定 </view>
				</view>
			</view>
			<view class="next-tree-view" :style="'top:' + (_showTreeBar ? '72rpx' : '0rpx')">
				<slot name="bottomBar"></slot>
				<next-search-more v-if="ifSearch" @search="onSearch" mode="center" :placeholder="placeholder" :isFixedSearchBtn="false" />
				<slot name="topBar"></slot>
				<scroll-view class="next-tree-view-sc" :scroll-top="scrollTop" :scroll-y="true">
					<view v-if="_treeList.length">
						<block v-for="(item, index) in _treeList" :key="index">
							<view class="next-tree-item-block" v-if="item.show">
								<view
									class="next-tree-item"
									:style="[
										{
											paddingLeft: item.rank * 15 + 'px',
											zIndex: item.rank * -1 + 50,
										},
									]"
									:class="{
										border: border === true,
										show: item.show,
										last: item.lastRank,
										showchild: item.showChild,
										open: item.open,
										disabled: item.disabled === true,
									}"
								>
									<block v-if="showAuxiliaryLine">
										<template v-if="item.rank > 1">
											<view
												:key="i"
												v-for="i in item.rank - 1"
												:style="{ left: 6 * (2 * i - 1) + 3 * (i - 1) + 'px' }"
												class="parent-horizontal-line"
											></view>
										</template>
										<view class="left-line">
											<view v-if="item.lastRank" class="horizontal-line"></view>
										</view>
									</block>
									<view class="next-tree-label" @tap.stop="_treeItemTap(item, index)">
										<image class="next-tree-icon" :src="item.lastRank ? lastIcon : item.showChild ? currentIcon : defaultIcon"></image>
										<input
											@click.stop
											@tap.stop
											class="label-input"
											placeholder="请输入"
											v-if="funcMode === 'edit' && item.status === 'edit'"
											v-model="item.name"
										/>
										<rich-text
											:nodes="getNodes(item.ouputText)"
											:selectable="false"
											v-else-if="ifSearch && searchModel === 'depHighlight' && keywords"
										></rich-text>
										<slot v-else-if="$slots.label" name="label" :data="_getLabelSlotData(item)"></slot>
										<rich-text v-else-if="item.checked && !item.disabled" :nodes="getThemeNodes(item.name)"></rich-text>
										<text v-else>{{ item.name }}</text>
									</view>
									<template v-if="['checkbox', 'radio'].indexOf(funcMode) !== -1">
										<view class="next-tree-check" @tap.stop="_treeItemSelect(item, index)" v-if="selectParent === true ? true : item.lastRank">
											<view
												class="next-tree-check-yes"
												v-if="item.checked"
												:class="{ radio: !multiple }"
												:style="{
													'border-color': item.disabled ? '#ccc' : _themeColor,
													'background-color': item.disabled ? '#ccc' : _themeColor,
												}"
											>
												<view
													class="next-tree-check-yes-b"
													:style="{
														'background-color': item.disabled ? '#ccc' : _themeColor,
													}"
												>
													<text v-if="item.checked" class="icon-text">✔</text>
												</view>
											</view>
											<view
												class="next-tree-check-no"
												v-else
												:class="{ radio: !multiple }"
												:style="{
													'border-color': item.disabled ? '#ccc' : _themeColor,
												}"
											>
												<text
													v-if="showHalfChecked(item) && showHalfCheckedTips"
													:style="{
														color: item.disabled ? '#ccc' : _themeColor,
														'font-weight': 'blod',
														'font-size': '10px',
													}"
													class="icon-text"
												>
													一
												</text>
											</view>
										</view>
									</template>
									<template v-else-if="funcMode === 'edit'">
										<text v-if="item.status === 'loading'" :style="{ color: '#ccc' }" class="iconfont-loading icon-btn"> &#xe629; </text>
										<view v-else>
											<text
												@click="_complete(item)"
												v-if="item.status === 'edit'"
												:style="{ color: item.disabled ? '#ccc' : _themeColor }"
												class="iconfont icon-btn"
											>
												&#xe6cf;
											</text>
											<template v-else>
												<text
													@click="_editItem(item)"
													:style="{
														color: item.disabled ? '#ccc' : _themeColor,
													}"
													class="iconfont icon-btn"
												>
													&#xe66e;
												</text>
												<text @click="_addSubItem(item)" :style="{ color: item.disabled ? '#ccc' : '#333' }" class="iconfont icon-btn">
													&#xe664;
												</text>
												<text @click="_addSameItem(item)" :style="{ color: item.disabled ? '#ccc' : '#333' }" class="iconfont icon-btn">
													&#xe601;
												</text>
											</template>
											<text @click="_delItem(item)" :style="{ color: item.disabled ? '#ccc' : '#ff4d4f' }" class="iconfont icon-btn"> &#xe602; </text>
										</view>
									</template>
								</view>
							</view>
						</block>
					</view>
					<view v-else>
						<slot v-if="$slots.empty" name="empty"></slot>
						<view class="empty" v-else><text>暂无数据</text></view>
					</view>
					<!--<view v-if="ifSearch" style="height: 80rpx"></view>-->
				</scroll-view>
			</view>
		</view>
		<view class="fixed-bottom-bar"><slot name="fixedBottomBar"></slot></view>
	</view>
</template>

<script>
import NextSearchMore from '../../../next-search-more/components/next-search-more/next-search-more.vue';

export default {
	name: 'next-tree',
	components: { NextSearchMore },
	props: {
		uiMode: {
			type: String,
			default: 'popup', // popup(弹窗), page(页面)
		},
		funcMode: {
			type: String,
			default: 'radio', // display(展示模式), edit(编辑模式), checkbox(多选模式), radio(单选模式)
		},
		treeData: {
			type: Array,
			default: function () {
				return [];
			},
		},
		valueKey: {
			type: String,
			default: 'id',
		},
		labelKey: {
			type: String,
			default: 'label',
		},
		disabledKey: {
			type: String,
			default: 'disabled',
		},
		childrenKey: {
			type: String,
			default: 'children',
		},
		title: {
			type: [String, Function],
			default: '',
		},
		selectParent: {
			//是否可以选父级
			type: Boolean,
			default: false,
		},
		foldAll: {
			//折叠时关闭所有已经打开的子集，再次打开时需要一级一级打开
			type: Boolean,
			default: false,
		},
		themeColor: {
			// 主题颜色
			type: String,
			default: '#f9ae3d', // #f9ae3d
		},
		cancelColor: {
			// 取消按钮颜色
			type: String,
			default: '', // #757575
		},
		titleColor: {
			// 标题颜色
			type: String,
			default: '', // #757575
		},
		currentIcon: {
			// 展开时候的ic
			type: String,
			default:
				'',
		},
		defaultIcon: {
			// 折叠时候的ic
			type: String,
			default:
				'',
		},
		lastIcon: {
			// 没有子集的ic
			type: String,
			default: '',
		},
		border: {
			// 是否有分割线
			type: Boolean,
			default: false,
		},
		checkStrictly: {
			// 只有在funcMode为checkbox状态下生效； 状态下节点选择完全受控（父子节点选中状态不再关联）
			type: Boolean,
			default: false,
		},
		checkStrictlyModel: {
			// 关联模式 weak: 弱关联；strong: 强关联
			type: String,
			default: 'weak',
		},
		showHalfCheckedTips: {
			// 只有在funcMode为checkbox, checkStrictly为false状态下生效； 父子节点选中状态不再关联，显示半选提示
			type: Boolean,
			default: true,
		},
		ifSearch: {
			// 是否开启search模式
			type: Boolean,
			default: true,
		},
		searchModel: {
			// 搜索模式配置
			type: String,
			default: 'common', // depHighlight: 从属高亮；common: 一般；remote：远程
		},
		showAuxiliaryLine: {
			// 辅助线模式
			type: Boolean,
			default: false,
		},
		loadData: {
			type: Function,
		},
		height: {
			type: Number,
			default: 500,
		},
		changeVerify: {
			type: Function,
		},
		expandedKeys: {
			// (Controlled) Specifies the keys of the expanded treeNodes
			type: Array,
			default: () => [],
		},
		expandedMode: {
			// common:  一般模式；singe: 单一模式；
			type: String,
			default: 'common',
		},
		placeholder: {
			type: String,
			default: '请输入人员姓名',
		},
	},
	data() {
		return {
			showTree: false,
			treeList: [],
			currentTreeData: [],
			selectIndex: -1,
			keywords: '',
			nodeInitContrl: {},
			top: '',
			initNum: 1,
			scrollTop: 0,
		};
	},
	options: {
		styleIsolation: 'shared',
	},
	computed: {
		_showTreeBar() {
			return this.uiMode === 'popup';
		},
		_themeColor() {
			return this.themeColor || '#f9ae3d';
		},
		_treeList() {
			let tempList = [];
			if (this.ifSearch && this.keywords) {
				let arr = this.treeList.filter((item) => {
					return item.name && item.name.indexOf(this.keywords) !== -1;
				});
				arr.forEach((otem) => {
					if (otem.parentId.length > 0) {
						otem.parentId.forEach((id, index) => {
							this.treeList.forEach((u) => {
								if (id === u.id) {
									u.show = true;
									u.showChild = true;
									otem.show = true;
									tempList.push(u);
									if (index === otem.parentId.length - 1) {
										tempList.push(otem);
									}
								}
							});
						});
					}
				});
				tempList = this.unique(tempList);
				return tempList;
			} else {
				return this.treeList;
			}
			//   return this.treeList
			//     .filter((item) => {
			//       return item.name && item.name.indexOf(this.keywords) !== -1;
			//     })
			//     .map((item) => {
			//       const o = JSON.parse(JSON.stringify(item));
			//       if (o.showChild === false) {
			//         o.showChild = true;
			//       }
			//       if (o.show === false) {
			//         o.show = true;
			//       }
			//       return o;
			//     });
			// } else {
			//   return this.treeList;
			// }
		},

		customTitle() {
			if (typeof this.title === 'function') {
				return this.title(this._getCheckedParams());
			} else {
				return this.title;
			}
		},
		multiple() {
			if (this.funcMode === 'checkbox') {
				return true;
			} else if (this.funcMode === 'radio') {
				return false;
			} else {
				return true;
			}
		},
	},
	methods: {
		//去重
		unique(arr) {
			return Array.from(new Set(arr));
		},
		_show() {
			this.showTree = true;
		},
		_hide() {
			this.showTree = false;
		},
		_cancel() {
			this._hide();
			this.$emit('cancel', '');
		},
		_confirm() {
			// 处理所选数据
			let rt = this._getCheckedParams();
			this._hide();

			this.$emit('confirm', rt);
		},
		_getLabelSlotData(item) {
			const _it = this.getItemFromTreeData(this.currentTreeData, item.id);
			const it = Object.assign({}, _it);
			delete it[this.childrenKey];
			return it;
		},
		_getCheckedParams() {
			// 处理所选数据
			let rt = [],
				obj = {};
			this.treeList.forEach((v, i) => {
				if (this.treeList[i].checked) {
					obj = {};
					obj.parents = this.treeList[i].parents;
					obj = Object.assign(obj, this.treeList[i].source);
					// 移除子元素
					delete obj.children;
					rt.push(obj);
				}
			});
			return rt;
		},
		_addSubItem(item) {
			if (item.disabled) return;
			const it = Object.assign({}, item);
			if (item.lastRank) {
				item.lastRank = false;
				item.showChild = true;
			}
			this.$nextTick(() => {
				this.initNum++;
				const parentId = item.parentId.concat([]);
				const parents = item.parents.concat([]);
				parentId.push(item.id);
				parents.push(item);
				it.disabled = false;
				it.rank = it.rank + 1;
				it.id = `next-tree-${this.initNum}`;
				it.parentId = [...parentId];
				it.parents = [...parents];
				it.show = true;
				it.showChild = false;
				it.open = false;
				it.name = '';
				it.status = 'edit';
				it.source = {};
				it.hideArr = [];
				it.lastRank = true;
				let index = -1;
				for (let i = this.treeList.length - 1; i >= 0; i--) {
					if (this.treeList[i].id === item.id) {
						index = i;
						break;
					}
				}
				if (index !== -1) {
					this.treeList.splice(index + 1, 0, it);
				}
			});
		},
		_addSameItem(item) {
			if (item.disabled) return;
			const it = Object.assign({}, item);
			let index = -1;
			for (let i = this.treeList.length - 1; i >= 0; i--) {
				if (this.treeList[i].id === item.id || this.treeList[i].parentId.indexOf(item.id) !== -1) {
					index = i;
					break;
				}
			}
			this.initNum++;
			it.id = `next-tree-${this.initNum}`;
			it.source = {};
			it.hideArr = [];
			it.name = '';
			it.status = 'edit';
			if (index !== -1) {
				this.treeList.splice(index + 1, 0, it);
			}
		},
		async _complete(item) {
			if (item.name) {
				item.status = 'loading';
				if (item.operateCallback) {
					await item.operateCallback('complete', item);
					await this.$nextTick();
				}
				item.status = '';
			} else {
				uni.showToast({
					title: '请先完善内容',
					icon: 'none',
				});
			}
		},
		_editItem(item) {
			if (item.disabled) return;
			item.status = 'edit';
		},
		_revert() {
			this.uiModeInit();
		},
		async _delItem(item) {
			if (item.disabled) return;
			item.status = 'loading';
			if (item.operateCallback) {
				await item.operateCallback('delete', item);
				await this.$nextTick();
			}
			this.delItemFunc(item);
		},
		delItemFunc(item) {
			const id = item && item.id ? item.id : '';
			const ids = [];
			this.treeList.map((it, index) => {
				if (it.id === id) {
					ids.push(index);
				} else if (it.parentId.indexOf(id) !== -1) {
					ids.push(index);
				}
			});
			ids.sort((a, b) => b - a);
			ids.forEach((index) => {
				this.treeList.splice(index, 1);
			});
		},
		checkedFunc(values, state = true) {
			if (values instanceof Array) {
				values.map((id) => {
					const item = this.treeList.find((it) => it.id === id);
					if (item) {
						item.checked = !!state;
					}
				});
			} else {
				const _item = this.treeList.find((it) => it.id === values);
				if (_item) {
					_item.checked = !!state;
				}
			}
		},
		getRenderTreeList(list = [], rank = 0, parentId = [], parents = []) {
			const treeList = [];
			list.forEach((item) => {
				const halfChecked = this.getHalfCheckedFormTreeData(item);
				let ouputText = '';
				if (this.searchModel === 'depHighlight') {
					if (parents && parents.length) {
						ouputText = parents.map((item) => item[this.labelKey]).join(' > ');
						ouputText = ouputText + ' > ' + item[this.labelKey];
					} else {
						ouputText = item[this.labelKey];
					}
				}
				const bool1 = this.expandedKeys.indexOf(item[this.valueKey]) !== -1;
				const len = parentId.length;
				const bool2 = len > 0 ? this.expandedKeys.indexOf(parentId[len - 1]) !== -1 : bool1;
				treeList.push({
					id: item[this.valueKey],
					name: item[this.labelKey],
					source: item,
					parentId, // 父级id数组
					parents, // 父级id数组
					rank, // 层级
					showChild: !bool1, //子级是否显示
					open: !bool1, //是否打开
					show: !bool1 || bool2 || rank === 0, // 自身是否显示
					hideArr: [],
					ouputText,
					orChecked: item.checked ? item.checked : false,
					checked: item.checked ? item.checked : false,
					halfChecked,
					disabled: this.disabledKey && item[this.disabledKey] === true,
					status: '',
					operateCallback: typeof item.operateCallback === 'function' ? item.operateCallback : undefined,
				});
				if (bool1) {
					this.nodeInitContrl[item[this.valueKey]] = true;
				} else {
					this.nodeInitContrl[item[this.valueKey]] = undefined;
				}
				if (
					(Array.isArray(item[this.childrenKey]) && item[this.childrenKey].length > 0) ||
					(this.loadData && Array.isArray(item[this.childrenKey]) && item[this.childrenKey].length === 0)
				) {
					let parentid = [...parentId],
						parentArr = [...parents],
						childrenid = [];
					delete parentArr.children;
					parentid.push(item[this.valueKey]);
					parentArr.push({
						[this.valueKey]: item[this.valueKey],
						[this.labelKey]: item[this.labelKey],
					});
				} else if (item[this.childrenKey] === null) {
					treeList[treeList.length - 1].lastRank = false;
				} else {
					treeList[treeList.length - 1].lastRank = true;
				}
			});
			return treeList;
		},
		//扁平化树结构
		_renderTreeList(list = [], rank = 0, parentId = [], parents = []) {
			list.forEach((item) => {
				const halfChecked = this.getHalfCheckedFormTreeData(item);
				let ouputText = '';
				if (this.searchModel === 'depHighlight') {
					if (parents && parents.length) {
						ouputText = parents.map((item) => item[this.labelKey]).join(' > ');
						ouputText = ouputText + ' > ' + item[this.labelKey];
					} else {
						ouputText = item[this.labelKey];
					}
				}
				const bool1 = this.expandedKeys.indexOf(item[this.valueKey]) !== -1;
				const len = parentId.length;
				const bool2 = len > 0 ? this.expandedKeys.indexOf(parentId[len - 1]) !== -1 : bool1;
				this.treeList.push({
					id: item[this.valueKey],
					name: item[this.labelKey],
					source: item,
					parentId, // 父级id数组
					parents, // 父级id数组
					rank, // 层级
					showChild: !bool1, //子级是否显示
					open: !bool1, //是否打开
					show: !bool1 || !bool2 || rank === 0, // 自身是否显示
					hideArr: [],
					ouputText,
					orChecked: item.checked ? item.checked : false,
					checked: item.checked ? item.checked : false,
					halfChecked,
					disabled: this.disabledKey && item[this.disabledKey] === true,
					status: '',
					operateCallback: typeof item.operateCallback === 'function' ? item.operateCallback : undefined,
				});
				if (bool1) {
					this.nodeInitContrl[item[this.valueKey]] = true;
				} else {
					this.nodeInitContrl[item[this.valueKey]] = undefined;
				}
				if (
					(Array.isArray(item[this.childrenKey]) && item[this.childrenKey].length > 0) ||
					(this.loadData && Array.isArray(item[this.childrenKey]) && item[this.childrenKey].length === 0)
				) {
					let parentid = [...parentId],
						parentArr = [...parents],
						childrenid = [];
					delete parentArr.children;
					parentid.push(item[this.valueKey]);
					parentArr.push({
						[this.valueKey]: item[this.valueKey],
						[this.labelKey]: item[this.labelKey],
					});
					this._renderTreeList(item[this.childrenKey], rank + 1, parentid, parentArr);
				} else if (item[this.childrenKey] === null) {
					this.treeList[this.treeList.length - 1].lastRank = false;
				} else {
					this.treeList[this.treeList.length - 1].lastRank = true;
				}
			});
		},
		// 处理默认选择
		_defaultSelect() {
			this.treeList.forEach((v, i) => {
				if (v.checked) {
					this.treeList.forEach((v2, i2) => {
						if (v.parentId.toString().indexOf(v2.parentId.toString()) >= 0) {
							v2.show = true;
							if (v.parentId.includes(v2.id)) {
								v2.showChild = true;
								v2.open = true;
							}
						}
					});
				}
			});
		},
		getTreeList() {
			return this.treeList;
		},
		// 点击
		async _treeItemTap(item, _index) {
			const index = this.treeList.findIndex((it) => it.id === item.id);
			this.scrollTop = index * 40;
			if (item.lastRank === true) {
				if (item.disabled === true) return;
				if (['checkbox', 'radio'].indexOf(this.funcMode) === -1) return;
				//点击最后一级时触发事件
				this.treeList[index].checked = !this.treeList[index].checked;

				if (this.changeVerify && typeof this.changeVerify === 'function') {
					const current = Object.assign({}, item.source);
					current.checked = item.checked;
					const tip = this.changeVerify(current, this.multiple ? this._getCheckedParams() : [current]);
					if (tip) {
						this.treeList[index].checked = !this.treeList[index].checked;
						uni.showToast({
							title: tip,
							icon: 'none',
						});
						return;
					}
				}
				this.treeList[index].halfChecked = false;
				if (this.multiple && !this.checkStrictly && this.showHalfCheckedTips) {
					this.updateHalfChecked(index);
				} else if (this.multiple && this.checkStrictly) {
					this.updateParentChecked(index);
				}
				this._fixMultiple(index);
				this.$emit('change', this._getCheckedParams());
				return;
			} else if (this.ifSearch && this.keywords) {
				// 搜索模式下不处理展开收起逻辑
				return;
			}
			// loadData实现
			const isLoadData = this.loadData && !this.nodeInitContrl[item.id];
			if (isLoadData) {
				uni && uni.showLoading({ title: '请稍后...' });
				const newChild = await this.loadData({
					$type: 'nodeLoad',
					source: this.treeList[index].source,
				});
				// 为了保证treeData数据的完整性，异步加载的数据需要添加到treeData上；
				const treeItem = this.getItemFromTreeData(this.currentTreeData, item.id);
				treeItem[this.childrenKey] = newChild && newChild.length ? newChild : undefined;
				const parentId = item.parentId || [];
				const lists = this.getRenderTreeList(newChild || [], item.rank + 1, parentId.concat([item.id]), [
					{
						[this.valueKey]: item[this.valueKey],
						[this.labelKey]: item[this.labelKey],
					},
				]);
				this.nodeInitContrl[item.id] = true;
				this.treeList.splice(index + 1, 0, ...lists);
			}
			const childLen = this.treeList.filter((it) => it.parentId.includes(item.id)).length;
			if (!isLoadData && childLen > 50) {
				uni && uni.showLoading({ title: '请稍后...' });
			}
			let list = this.treeList;
			let id = item.id;
			item.showChild = !item.showChild;
			item.open = item.showChild ? true : !item.open;
			list.forEach((childItem, i) => {
				if (item.showChild === false) {
					//隐藏所有子级
					if (!childItem.parentId.includes(id)) {
						return;
					} else {
						if (!this.foldAll) {
							if (childItem.lastRank !== true && !childItem.open) {
								childItem.showChild = false;
							}
							// 为隐藏的内容添加一个标记
							if (childItem.show) {
								childItem.hideArr[item.rank] = id;
							}
						} else {
							if (childItem.lastRank !== true) {
								childItem.showChild = false;
							}
						}
						childItem.show = false;
					}
				} else {
					// 打开子集
					if (childItem.parentId[childItem.parentId.length - 1] === id) {
						childItem.show = true;
					}

					// 打开被隐藏的子集
					if (childItem.parentId.includes(id) && !this.foldAll) {
						if (childItem.hideArr[item.rank] === id) {
							childItem.show = true;
							if (childItem.open && childItem.showChild) {
								childItem.showChild = true;
							} else {
								childItem.showChild = false;
							}
							childItem.hideArr[item.rank] = null;
						}
					} else if (this.expandedMode === 'singe' && !childItem.parentId.includes(id)) {
						if (childItem.id !== id) {
							const bool1 = item.parentId.some((id) => {
								return (childItem.parentId && childItem.parentId.indexOf(id) !== -1) || childItem.rank === 0;
							});
							const childItemParentId = [...childItem.parentId];
							const _id = childItemParentId ? childItemParentId.pop() : '';
							const nodeList = [item, { parentId: childItemParentId.length ? childItemParentId : [] }];
							if (!childItem.lastRank) {
								if (item.parentId.indexOf(childItem.id) === -1) {
									childItem.showChild = false;
								}

								if (!bool1 && !this.isSiblingNode([item, childItem])) {
									childItem.show = false;
								} else if (childItem.rank !== 0 && _id !== id && this.isSiblingNode(nodeList)) {
									childItem.show = false;
								} else if (childItem.rank !== 0 && _id !== id && !this.isSiblingNode(nodeList) && this.isParentSiblingNode(nodeList)) {
									childItem.show = false;
								}
							} else {
								if (!this.isSiblingNode([item, childItem]) && !bool1) {
									childItem.show = false;
								} else if (_id !== id && this.isSiblingNode(nodeList)) {
									childItem.show = false;
								} else if (_id !== id && !this.isSiblingNode(nodeList) && this.isParentSiblingNode(nodeList)) {
									childItem.show = false;
								}
							}
						}
					}
				}
			});
			setTimeout(() => {
				uni && uni.hideLoading();
			});
		},
		isSiblingNode(targetArr = []) {
			const target1 = targetArr && targetArr.length ? targetArr[0] : {};
			let target1Id = '';
			if (target1.parentId && target1.parentId.length) {
				target1Id = target1.parentId[target1.parentId.length - 1];
			}
			return targetArr.every((item) => {
				if (item && item.parentId && item.parentId.length) {
					return target1Id === item.parentId[item.parentId.length - 1];
				} else {
					return target1Id === '';
				}
			});
		},
		isParentSiblingNode(targetArr = []) {
			const target1 = targetArr && targetArr.length ? targetArr[0] : {};
			let target1Id = '';
			if (target1.parentId && target1.parentId.length) {
				target1Id = target1.parentId[target1.parentId.length - 1];
			}
			return targetArr.every((item) => {
				if (item && item.parentId && item.parentId.length) {
					return item.parentId.some((id) => id === target1Id) && target1Id !== '';
				} else {
					return target1Id === '';
				}
			});
		},
		getThemeNodes(text) {
			const _text = (text || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
			const regex = new RegExp(`(${text || ''})`, 'gi');
			return text ? text.replace(regex, `<span style="color: ${this._themeColor}">$1</span>`) : '';
		},
		getNodes(ouputText) {
			if (this.keywords && ouputText) {
				const key = (this.keywords || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
				const regex = new RegExp(`(${key})`, 'gi');
				return ouputText.replace(regex, `<span style="color: ${this._themeColor}">$1</span>`);
			}
			return ouputText;
		},
		getHalfCheckedFormTreeData(item) {
			if (this.checkStrictly) {
				return false;
			} else if (!this.showHalfCheckedTips) {
				return false;
			} else {
				if (item[this.childrenKey] && item[this.childrenKey].length) {
					return item[this.childrenKey].some((it) => {
						if (it.checked === true) {
							return true;
						} else if (it[this.childrenKey] && it[this.childrenKey].length) {
							return this.getHalfCheckedFormTreeData(it);
						} else {
							return false;
						}
					});
				} else {
					return false;
				}
			}
		},
		getItemFromTreeData(treeData, id) {
			if (id) {
				let item = null;
				(treeData || []).some((it) => {
					if (it[this.valueKey] === id) {
						item = it;
						return true;
					} else if (it[this.childrenKey] && it[this.childrenKey].length) {
						item = this.getItemFromTreeData(it[this.childrenKey], id);
						return !!item;
					} else {
						return false;
					}
				});
				return item;
			}
			return null;
		},
		_treeItemSelect(item, _index) {
			const index = this.treeList.findIndex((it) => it.id === item.id);
			if (item.disabled === true) return;
			this.treeList[index].checked = !this.treeList[index].checked;

			if (this.changeVerify && typeof this.changeVerify === 'function') {
				const current = Object.assign({}, item.source);
				current.checked = item.checked;
				const tip = this.changeVerify(current, this.multiple ? this._getCheckedParams() : [current]);
				if (tip) {
					this.treeList[index].checked = !this.treeList[index].checked;
					uni.showToast({
						title: tip,
						icon: 'none',
					});
					return;
				}
			}
			this.treeList[index].halfChecked = false;
			if (this.multiple && this.checkStrictly) {
				if (!item.lastRank) {
					const source = item.source || {};
					const children = source[this.childrenKey] || [];
					const checkedKeyList = this.getChildrenKeys(children);
					this.treeList.forEach((v, i) => {
						if (checkedKeyList.indexOf(v.id) !== -1) {
							if (this.checkStrictlyModel === 'weak') {
								if (!this.treeList[i].disabled) {
									this.treeList[i].checked = this.treeList[index].checked;
								}
							} else if (this.checkStrictlyModel === 'strong') {
								this.treeList[i].checked = this.treeList[index].checked;
							}
						}
					});
				}
				this.updateParentChecked(index);
			} else if (this.multiple && !this.checkStrictly && this.showHalfCheckedTips) {
				this.updateHalfChecked(index);
			} else {
				this._fixMultiple(index);
			}

			this.$emit('change', this._getCheckedParams());
		},
		updateParentChecked(index) {
			const parentId = (this.treeList[index].parentId || []).concat([]).reverse();
			if (parentId && parentId.length) {
				parentId.map((id) => {
					const parentTreeDataItem = this.getItemFromTreeData(this.currentTreeData, id);
					const childrenIds = (parentTreeDataItem[this.childrenKey] || []).map((item) => item[this.valueKey]);
					const bool = this.treeList.filter((it) => childrenIds.indexOf(it.id) !== -1).every((it) => it.checked === true);

					const _bool = this.treeList.filter((it) => childrenIds.indexOf(it.id) !== -1).every((it) => it.checked === false);

					const parentItem = this.treeList.find((it) => it.id === id);
					if (parentItem) {
						if (this.checkStrictlyModel === 'weak') {
							if (bool && !parentItem.disabled) {
								parentItem.checked = true;
							} else if (_bool && !parentItem.disabled) {
								parentItem.checked = false;
							}
						} else if (this.checkStrictlyModel === 'strong') {
							if (bool) {
								parentItem.checked = true;
							} else {
								parentItem.checked = false;
							}
						}
					}
				});
			}
		},
		updateHalfChecked(index) {
			const _parentId = this.treeList[index].parentId || [];
			const parentId = _parentId.concat([]).reverse();
			if (parentId && parentId.length) {
				parentId.map((id) => {
					const parentTreeDataItem = this.getItemFromTreeData(this.currentTreeData, id);
					const childrenIds = (parentTreeDataItem[this.childrenKey] || []).map((item) => item[this.valueKey]);

					const bool = this.treeList
						.filter((it) => childrenIds.indexOf(it.id) !== -1)
						.every((it) => it.checked === false && it.halfChecked === false);

					const _bool = this.treeList.filter((it) => childrenIds.indexOf(it.id) !== -1).some((it) => it.checked === true || it.halfChecked === true);

					const parentItem = this.treeList.find((it) => it.id === id);
					if (parentItem) {
						if (!parentItem.checked) {
							if (bool) {
								parentItem.halfChecked = false;
							} else if (_bool) {
								parentItem.halfChecked = true;
							} else {
								parentItem.halfChecked = false;
							}
						}
					}
				});
			}
			if (this.treeList[index].checked == false) {
				const source = this.treeList[index].source || {};
				const children = source[this.childrenKey] || [];
				const checkedKeyList = this.getChildrenKeys(children);
				const bool = this.treeList.filter((item) => checkedKeyList.indexOf(item.id) !== -1).some((item) => item.checked);
				if (bool) {
					this.treeList[index].halfChecked = true;
				}
			}
		},
		showHalfChecked(item) {
			if (this.multiple && !this.checkStrictly && item.halfChecked === true) {
				return true;
			} else {
				return false;
			}
		},
		getChildrenKeys(children) {
			let keys = [];
			(children || []).map((item) => {
				keys.push(item[this.valueKey]);
				if (item[this.childrenKey] && item[this.childrenKey].length) {
					keys = keys.concat(this.getChildrenKeys(item[this.childrenKey]));
				}
			});
			return keys;
		},
		// 处理单选多选
		_fixMultiple(index) {
			if (!this.multiple) {
				// 如果是单选
				this.treeList.forEach((v, i) => {
					if (i != index) {
						this.treeList[i].checked = false;
					} else {
						this.treeList[i].checked = true;
					}
				});
			}
		},
		// 重置数据
		_reTreeList() {
			this.treeList.forEach((v, i) => {
				this.treeList[i].checked = v.orChecked;
			});
		},
		_initTree() {
			this.treeList.length = 0;
			if (this.loadData) {
				this.currentTreeData = JSON.parse(JSON.stringify(this.treeData));
			} else {
				this.currentTreeData = this.treeData;
			}
			this._renderTreeList(this.currentTreeData);
			this.$nextTick(() => {
				this._defaultSelect();
			});
		},
		_clear() {
			this.treeList.map((item) => {
				if (this.multiple && this.checkStrictly) {
					if (this.checkStrictlyModel === 'strong') {
						item.checked = false;
					} else if (this.checkStrictlyModel === 'weak') {
						if (!item.disabled) {
							item.checked = false;
						}
					} else {
						item.checked = false;
					}
				} else {
					if (!item.disabled) {
						item.checked = false;
					}
				}

				item.halfChecked = false;
			});
			this.$emit('change', this._getCheckedParams());
			this.$emit('clear');
		},
		async onSearch(val) {
			if (this.searchModel === 'remote') {
				if (this.loadData) {
					if (val) {
						const newChild = await this.loadData({
							$type: 'remoteSearch',
							source: val,
						});
						const lists = this.getRenderTreeList(newChild);
						this.treeList = [...lists];
					} else {
						this._initTree();
					}
				} else {
					uni.showToast({
						title: '使用远程搜索模式，需要配置loadData函数；',
						icon: 'none',
					});
				}
			} else {
				this.keywords = val.trim();
			}
		},
		initUiModePopup(watched) {
			uni.getSystemInfo({
				success: (res) => {
					this.top = res.windowHeight - this.height + 'px';
				},
			});
			watched && watched();
			watched = this.$watch(
				() => this.showTree,
				(bool) => {
					if (bool) {
						this._initTree();
					} else {
						this.$nextTick(() => {
							setTimeout(() => {
								this.treeList.length = 0;
								this.nodeInitContrl = {};
							});
						});
					}
				},
				{ immediate: true }
			);
		},
		initUiModePage(watched) {
			this.top = '0px';
			watched && watched();
			watched = this.$watch(
				() => this.treeData,
				() => {
					this.treeList.length = 0;
					this.nodeInitContrl = {};
					this.$nextTick(() => {
						this._initTree();
					});
				},
				{ immediate: true, deep: true }
			);
			this.$nextTick(() => {
				this.showTree = true;
			});
		},
		uiModeInit() {
			let watched = null;
			if (this.uiMode === 'popup') {
				this.initUiModePopup(watched);
			} else if (this.uiMode === 'page') {
				this.initUiModePage(watched);
			} else {
				this.initUiModePopup(watched);
			}
		},
	},
	mounted() {
		this.uiModeInit();
	},
};
</script>

<style scoped>
@import './style.css';
</style>
